package com.vc.core;

import java.lang.reflect.Method;

import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;

import com.vc.audio.VcAudioManager;
import com.vc.opengl.GLRender;

/**
 * 遥控器类，如果涉及到UI操作的话，通过发广播的形式，由注册了该广播的activity接收
 * @author Administrator
 *
 */
public class VideoController implements IVideoEventListener,IAudioEventListener{

	  private static String TAG = "VideoController";
	  private VcCamera mVcCamera = null;
	  Context appContext;
	  public boolean mPauseVideo = false;//是否视频处于暂停状态，例如切换到语音聊天时，视频暂停
	  Application app;
	  
	  int[] screenSize = null;
	  
	  private static boolean soloaded = false;

	  //声音管理器
	  VcAudioManager mAudioManager = null;
	  private boolean mPauseAudio = false;//是否语音处于暂停状态，例如视频通话时关闭声音
	  private boolean mMute = false;
	  private int mAudioMode = 0;
	  
	  private static VideoController mInstance = null;
	  

	  public static final int DEVICE_SUPPORT = 0;     //具备视频能力
	  public static final int DEVICE_NOT_SUPPORT = 1; //设备不具备视频能力
	  public static final int SDK_NOT_SUPPORT = 2;    //SDK版本过低不具备视频能力
		
	  public static byte[] audioBuffer;
	  private VideoController(){}
	  
	  /**
	   * 单例模式
	   * @return
	   */
	 public static VideoController getInstance(){
	    if (mInstance == null) {
	      mInstance = new VideoController();
	      if (!soloaded) {
		      System.loadLibrary("VideoController");
		      soloaded = true;
		  }
	    }
	    return mInstance;
	 }
	  
	 /**
	  * 初始化控制器
	  */
	 private void initVcController()
	 {
	     screenSize = getScreenSize();
	     mAudioManager = new VcAudioManager(this);
	     
	     //TODO 测试，要删除
	     audioBuffer = new byte[8192];
	     if (mAudioManager != null) {
			mAudioManager.InitAudio(appContext, isMicphoneMute(), getCurrentAudioMode());
			mAudioManager.StartAudio();
		 }
	 }
	  
	  /**
	   * 获取屏幕宽高
	   * @return
	   */
	 private int[] getScreenSize() {
	    int[] wh = new int[2];
	    WindowManager mWindowManager = (WindowManager)this.appContext.getSystemService("window");
	    DisplayMetrics displaysMetrics = new DisplayMetrics();
	    mWindowManager.getDefaultDisplay().getMetrics(displaysMetrics);
	    wh[0] = displaysMetrics.widthPixels;
	    wh[1] = displaysMetrics.heightPixels;
	    return wh;
	 }
	  
	 /**
	  * 设置application
	  * @param app
	  */
	public void setAppRuntime(Application app) {
	    this.app = app;
	    this.appContext = app.getApplicationContext();
		initVcController();
	}
	 
	/**
	 * 发广播，一些通知UI方面的操作可以通过此广播发出去
	 * @param account 帐号
	 * @param type 类型
	 */
	public void sendVideoMsgBroadcast(int type) {
		if (app != null) {
			Intent intent = new Intent();
			if (intent != null) {
				intent.setAction(VcConstants.ACTION_VIDEO_MSG);
				intent.putExtra("type", type);
				Log.d(TAG, "VideoMsgBroadcast:type="+type);
				app.sendBroadcast(intent);
			}
		}
	}
	
	/**
	 * 发送获取网关IP的请求，此处不做接收，仅仅向连接服务器上报
	 */
	public void sendGetGatewayIpReq() {
		//TODO 待实现，对服务器做一个请求。
	}
	
	/**
	 * 执行线程，此处作用是本地视频新开线程
	 * @param r
	 */
	public void execute(final Runnable r){
		//TODO 做线程池管理
		r.run();
	}
	  
	  
	/**
	* 发起视频请求
	* @param toAccount 向谁发起
	* @return
	*/
	public int requestVideoChat(long toAccount){
		int result = request(toAccount);
	    return result;
	}
	
	
	/**
	* 取消视频通话请求
	* @param toAccount 向谁取消
	*/
	public int cancelVideoChat(long toAccount) {
		int result = cancelRequest(toAccount);
		return result;
	}
	
	/**
	* 接受视频请求
	* @param toAccount 接受谁的视频请求
	* @return
	*/
	public int acceptedVideoChat(long toAccount){
		int result = accept(toAccount);
	    return result;
	}
	
	/**
	 * 暂停视频通话
	 * @return
	 */
	public int pauseVideoChat(){
		return -1;
	}
	
	/**
	 * 关闭视频通讯
	 * @param toAccount
	 * @return
	 */
	public int closeVideoChat(long toAccount){
		int result = close(toAccount);
		return result;
	}
	
	/**
	 * 切换到语音
	 * @param toAccount
	 * @return
	 */
	public int switchAudioChat(long toAccount){
		int result = switchAudio(toAccount);
		return result;
	}

	/**
	 * 切换到视频
	 * @param toAccount
	 * @return
	 */
	public int switchVideoChat(long toAccount){
		int result = switchVideo(toAccount);
		return result;
	}
	
	protected void finalize() throws Throwable{
	    super.finalize();
	}
	  
	/**
	* 获取摄像头
	* @return
	*/
	public VcCamera getVcCamera() {
		if(this.mVcCamera==null){
			this.mVcCamera = new VcCamera(this);
		}
		return this.mVcCamera;
	}
	
	/**
	 * 获取上下文
	 * @return
	 */
	public Context getAppContext(){
		return this.appContext;
	}
	
	/**
	 * 传递渲染器，这个渲染器应该是本地图像，待确定
	 * @param render
	 */
    public void setPeerGLRenderer(GLRender render){
    	setPeerGLRender(render); //JNI调用
    }

    /**
     * 设置相机id及旋转角度
     * @param cameraId
     * @param angle
     */
	public void setCameraAngle(int cameraId,int angle) {
		setCameraAngle(cameraId,angle);
	}
	
    /**
     * 发送数据
     * @param data
     * @param toAccount
     * @param width
     * @param height
     * @return
     */
	public int sendData(byte[] data, long toAccount, int width, int height){
		int result = -1;
		Log.d(TAG, "sendData begin data.length="+data.length+",width="+width+",height="+height);
		result = sendVideoData(
					data,
					toAccount,
					width,
					height,
					VcCamera.VideoChatSettings.getFormat(),
					VcCamera.VideoChatSettings.getnInFPS()
				);//JNI调用
		Log.d(TAG, "sendData end result="+result);
		return result;
	}
	
	
	/**
	* 获取设备IMEI串号
	* @return
	*/
	private String getDeviceIMEI() {
	    try {
	      Method m = TelephonyManager.class.getMethod("getDefault", new Class[0]);
	      TelephonyManager tm = (TelephonyManager)m.invoke(TelephonyManager.class, null);
	      return tm.getDeviceId();
	    }
	    catch (Exception localException) {
	    }
	    return null;
	}
	  
	/**
	 * 获取设备是否支持
	 * @return 0具备视频能力,  1设备不具备视频能力,  2sdk版本太低
	 */
	public static int bDeviceSupport() {
		String DEV_MODEL = android.os.Build.MODEL;
		String DEV_VERSION = android.os.Build.VERSION.INCREMENTAL;
		String DEV_MANUFACTURER = android.os.Build.MANUFACTURER;
		
		Log.d(TAG, "Model: " + DEV_MODEL + "\n"
				+ "Version: " + DEV_VERSION + "\n" 
				+ "Manufacturer: " + DEV_MANUFACTURER);
		
		if (android.os.Build.VERSION.SDK_INT < 8) {
			Log.d(TAG, "SDK_NOT_SUPPORT");
			return SDK_NOT_SUPPORT;
		}

		if (DEV_MANUFACTURER.equalsIgnoreCase("HUAWEI")) {
			if (DEV_MODEL.equalsIgnoreCase("C8500")) {
				Log.d(TAG, "DEVICE_NOT_SUPPORT");
				return DEVICE_NOT_SUPPORT;
			}
		}

		if (DEV_MANUFACTURER.equalsIgnoreCase("Samsung")) {
			if (DEV_MODEL.equalsIgnoreCase("GT-I5508")) {
				Log.d(TAG, "DEVICE_NOT_SUPPORT");
				return DEVICE_NOT_SUPPORT;
			}
		}

		if (DEV_MANUFACTURER.equalsIgnoreCase("FIH")) {
			if (DEV_MODEL.equalsIgnoreCase("SH8128U")) {
				Log.d(TAG, "DEVICE_NOT_SUPPORT");
				return DEVICE_NOT_SUPPORT;
			}
		}

		return DEVICE_SUPPORT;
	}
	
	//设置相机旋转角度
	public native int setCameraAngleFix(int cameraId, int angle);

	//发送视频请求
	native int request(long toAccount);

	//接受视频请求
	native int accept(long toAccount);
	
	//取消视频请求
	native int cancelRequest(long toAccount);

	//关闭视频通讯
	native int close(long toAccount);
	
	//设置渲染器，这个是用于本地吧
	native void setPeerGLRender(GLRender glRender);
	
	//主动发送视频数据
	native int sendVideoData(byte[] data, long toAccount, int width, int height, int format,int fps);

	//主动发起暂停视频
	native int PauseVideo(long toAccount);
	
	//切换到视频聊天
	native int switchVideo(long toAccount);
	
	//切换到语音聊天
	native int switchAudio(long toAccount);

	//继续视频，暂停的前提下
	native int ResumeVideo(long toAccount);
	
	//发送音频数据，由前台写入
	native int AudioInData(byte[] recData, int len);

	//获取音频数据，由后台写入playData
	native int AudioOutData(byte[] playData, int len);

	//设置输入静音，由前台发起
	native int SetAudioInputMute(long account, boolean enable);

	//设置输出静音，由前台发起
	native int SetAudioOutputMute(long account, boolean enable);

	//设置声音大小，由前台发起
	native int SetAudioSpeakerVolume(int value);

	//获取音频设备参数
	native int GetAudioDeviceParam(int[] mFormat, int[] mSamplerate, int[] mFrameLen, int[] mWorkmode);
	
	/**
	 * 唯一的回调方法，由JNI底层C++来调用
	 * @param eventId
	 * @param detail
	 * @param info
	 * @param frmUin
	 */
	 private void callbackOnEvent(int eventId, byte[] detail, long info, long frmUin) {
		  switch (eventId){
		    case 1://收到对方的视频请求
		      onRequestVideo(frmUin);
		      break;
		    case 2://对方接收了视频请求
			  onAcceptedVideo(frmUin);
			  break;
		    case 3://连接建立成功，可以视频会话了
			  onChannelReady(frmUin);
			  break;
		    case 4:
		      break;
		    case 5://对方版本不支持
		      onNotSupportVersion(frmUin);
		      break;
		    case 6://网络错误或连接错误
		      onNetworkError(frmUin, 0L);
		      onCloseVideo(frmUin, 1);
		      break;
		    case 7://暂停视频
		      onPauseVideo(frmUin);
		      break;
		    case 8://继续视频
		      onResumeVideo(frmUin);
		      break;
		  }
	}

	//-----------------------------------------华丽分割线，视频事件--------------------------------------------
	 
	/**
	 * 来了视频请求，该事件是由NotifyVideoActivity来触发的
	 */
	@Override
	public void onRequestVideo(long toAccount) {
		// TODO 发送请求的回调
		requestAudioFocus();// 获取音频焦点以暂停其他播放器播放的音乐
	}

	/**
	 * 取消发送视频请求的回调，该事件是由NotifyVideoActivity来触发的
	 */
	@Override
	public void onCancelRequest(long toAccount) {
		sendVideoMsgBroadcast(VcConstants.TYPE_FRIEND_CANCEL_REQUEST);		
		abandonAudioFocus();//释放音频焦点以使其他播放器继续播放音乐
	}

	/**
	 * 对方接受请求的回调
	 */
	@Override
	public void onAcceptedVideo(long toAccount) {
		//此处没什么动作，只有通道完全建立成功才可以进一步操作。
		//此处可以记录一下状态，视需求而定
	}
	
	/**
	 * 视频通讯管道建立成功
	 */
	@Override
	public void onChannelReady(long toAccount) {
		//有时候连通特别快  部分低端机窗口没有创建好  轮询等待窗口创建完成 100次超时
		Thread t = new Thread(new Runnable() {
			private int runTimes = 0;
			@Override
			public void run() {
				while(true){
					runTimes++;
					if (app != null) {
						
						//TODO 通知activity做UI的一些展现
						
						if(mAudioManager != null) {
							mAudioManager.InitAudio(appContext, isMicphoneMute(), getCurrentAudioMode());
							mAudioManager.StartAudio();//开始录音跟播音
						}
						Log.d(TAG, "Activity created after " + runTimes + " times");
						break;
					} else {
						if (runTimes >= 100) {
							Log.d(TAG, "Activity dosen't exist. Close video session.");
							sendVideoMsgBroadcast(VcConstants.TYPE_CONNECT_FAILED);
							break;
						} else {
							try {
								Thread.sleep(100);
							} catch (InterruptedException e) {}
						}
					}
				}
			}
		});
		t.start();
		
	}
	
	/**
	 * 对方关闭了视频
	 */
	@Override
	public void onCloseVideo(long paramLong, int paramInt) {
		sendVideoMsgBroadcast(VcConstants.TYPE_CLOSED_BY_FRIEND);
	}
	
	/**
	 * 对方SDK版本太低，无法视频
	 */
	@Override
	public void onNotSupportVersion(long fromAccount) {
		sendVideoMsgBroadcast(VcConstants.TYPE_SDK_NOT_SUPPORT);
	}


	/**
	 * 对方拒绝了你的视频请求
	 */
	@Override
	public void onRejectVideo(long paramLong) {
		sendVideoMsgBroadcast(VcConstants.TYPE_REJECT_BY_FRIEND);
	}
	
	/**
	 * 网络出错
	 */
	@Override
	public void onNetworkError(long fromAccount, long toAccount) {
		sendVideoMsgBroadcast(VcConstants.TYPE_NETWORK_ERRO);
	}

	/**
	 * 对方暂停了视频
	 */
	@Override
	public void onPauseVideo(long fromAccount) {
		// TODO 保存此时的状态，例如视频参数
	}

	/**
	 * 对方继续视频
	 */
	@Override
	public void onResumeVideo(long fromAccount) {
		// TODO 取视频参数
	}
	

	/**
	 * 对方暂停了声音
	 */
	@Override
	public void onPauseAudio(long paramLong) {
		// TODO Auto-generated method stub
		
	}

	/**
	 * 对方继续传送声音
	 */
	@Override
	public void onResumeAudio(long paramLong) {
		// TODO Auto-generated method stub
		
	}

	/**
	 * 对方发来语音通话请求
	 */
	@Override
	public void onRequestAudio(long paramLong) {
		//TODO 
	}
	
	
	
	//-----------------------------------------华丽分割线，语音事件---------------------------------------
	
	//声音管理器
	private AudioManager mAudioMgr = null;
	
	//声音焦点监听器
	private AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener = null;
	
	/**
	 * 获取声音焦点
	 */
	@SuppressLint("NewApi")
	private void requestAudioFocus() {
		if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.ECLAIR_MR1){
			return;
		}
		if (mAudioFocusChangeListener == null) {
			mAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
				@Override
				public void onAudioFocusChange(int focusChange) {
					if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
						// Stop playback
					} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
						// Pause playback
					} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
						// Lower the volume
					} else if(focusChange == AudioManager.AUDIOFOCUS_GAIN) {
						// Rusume playback or Raise it back normal
					}
				}
			};
		}
		if (mAudioMgr == null)
			mAudioMgr = (AudioManager) appContext.getSystemService(Context.AUDIO_SERVICE);
		if (mAudioMgr != null) {
			int ret = mAudioMgr.requestAudioFocus(mAudioFocusChangeListener,
					AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
			if (ret != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
				Log.d(TAG, "request audio focus fail. " + ret);
			}
		}
	}

	/**
	 * 释放声音焦点
	 */
	@SuppressLint("NewApi")
	private void abandonAudioFocus() {
		if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ECLAIR_MR1) {
			return;
		}
		if (mAudioMgr != null) {
			mAudioMgr.abandonAudioFocus(mAudioFocusChangeListener);
			mAudioMgr = null;
		}
	}
	
	/**
	 * 设置话筒静音模式
	 * 
	 * @param enable
	 * @return
	 */
	public int setAudioInputMute(boolean enable) {
		if (mAudioManager == null){
			return -1;
		}
		mPauseAudio = enable;
		Log.d(TAG, "M2M SetAudioInputMute: "  + enable);
		return mAudioManager.setAudioInputMute(enable);
	}

	/**
	 * 设置听筒静音模式
	 * 
	 * @param enable
	 * @return
	 */
	public int setAudioOutputMute(boolean enable) {
		if (mAudioManager == null){
			return -1;
		}
		return mAudioManager.setAudioOutputMute(enable);
	}

	/**
	 * 设置语音音量
	 * 
	 * @param volume
	 * @return
	 */
	public int setAudioVolume(int volume) {
		if (mAudioManager == null){
			return -1;
		}
		return mAudioManager.setAudioVolume(volume);
	}
	
	
	public VcAudioManager getMyAudioManager(){
		return mAudioManager;
	}
	
	
	public int getCurrentAudioMode() {
		return mAudioMode;
	}
	
	public boolean isMicphoneMute() {
		return mMute;
	}
	
	/**
	 * 获取音频硬件设备信息
	 */
	@Override
	public int getAudioDeviceInfo(int[] mFormat, int[] mSamplerate, int[] mFramelen, int[] mWorkmode) {
		Log.d(TAG, "GetAudioDeviceParam");
		int result = -1;
		//result = GetAudioDeviceParam(mFormat, mSamplerate, mFramelen, mWorkmode);//TODO JNI实现后放开
		return result;
	}

	/**
	 * 设置声音大小
	 */
	@Override
	public int setAudioSpeakeVolume(int value) {
		int result = -1;
		//result = SetAudioSpeakerVolume(value);
		Log.d(TAG, "setAudioSpeakeVolume|value="+value+",result="+result);//TODO JNI实现后放开
		return result;
	}

	/**
	 * 录音
	 */
	@Override
	public int recAudioData(byte[] recData, int len) {
		int result = -1;
		//System.arraycopy(recData, 0, audioBuffer, 0, len);
		result = AudioInData(recData,len);
		Log.d(TAG, "recAudioData|len="+len+",recData.length="+recData.length+",result="+result);
		return result;
	}

	/**
	 * 播放
	 */
	@Override
	public int playAudioData(byte[] playData, int len) {
		int result = -1;
		//System.arraycopy(audioBuffer, 0, playData, 0, len);
		result = AudioOutData(playData,len);
		Log.d(TAG, "playAudioData|len="+len+",playData.length="+playData.length+",result="+result);
		return result;
	}
}
